//! MIPI DCS (Display Command Set) Commands
//! 
//! This module provides standard MIPI DCS commands used for display control.
//! These commands are defined in the MIPI Alliance Specification for Display Command Set.

/// MIPI DSI Data Types
pub const MIPI_DSI_DCS_SHORT_WRITE: u8 = 0x05;
pub const MIPI_DSI_DCS_SHORT_WRITE_PARAM: u8 = 0x15;
pub const MIPI_DSI_DCS_LONG_WRITE: u8 = 0x39;
pub const MIPI_DSI_DCS_READ: u8 = 0x06;
pub const MIPI_DSI_GENERIC_SHORT_WRITE_0: u8 = 0x03;
pub const MIPI_DSI_GENERIC_SHORT_WRITE_1: u8 = 0x13;
pub const MIPI_DSI_GENERIC_SHORT_WRITE_2: u8 = 0x23;
pub const MIPI_DSI_GENERIC_LONG_WRITE: u8 = 0x29;

/// MIPI DCS Commands
/// 
/// Standard commands defined in MIPI DCS specification
#[allow(dead_code)]
pub mod dcs_cmd {
    /// Enter idle mode
    pub const ENTER_IDLE_MODE: u8 = 0x39;
    
    /// Enter invert mode
    pub const ENTER_INVERT_MODE: u8 = 0x21;
    
    /// Enter normal mode
    pub const ENTER_NORMAL_MODE: u8 = 0x13;
    
    /// Enter partial mode
    pub const ENTER_PARTIAL_MODE: u8 = 0x12;
    
    /// Enter sleep mode
    pub const ENTER_SLEEP_MODE: u8 = 0x10;
    
    /// Exit idle mode
    pub const EXIT_IDLE_MODE: u8 = 0x38;
    
    /// Exit invert mode
    pub const EXIT_INVERT_MODE: u8 = 0x20;
    
    /// Exit sleep mode
    pub const EXIT_SLEEP_MODE: u8 = 0x11;
    
    /// Get address mode
    pub const GET_ADDRESS_MODE: u8 = 0x0B;
    
    /// Get blue channel
    pub const GET_BLUE_CHANNEL: u8 = 0x08;
    
    /// Get diagnostic result
    pub const GET_DIAGNOSTIC_RESULT: u8 = 0x0F;
    
    /// Get display mode
    pub const GET_DISPLAY_MODE: u8 = 0x0D;
    
    /// Get green channel
    pub const GET_GREEN_CHANNEL: u8 = 0x07;
    
    /// Get pixel format
    pub const GET_PIXEL_FORMAT: u8 = 0x0C;
    
    /// Get power mode
    pub const GET_POWER_MODE: u8 = 0x0A;
    
    /// Get red channel
    pub const GET_RED_CHANNEL: u8 = 0x06;
    
    /// Get scanline
    pub const GET_SCANLINE: u8 = 0x45;
    
    /// Get signal mode
    pub const GET_SIGNAL_MODE: u8 = 0x0E;
    
    /// No operation
    pub const NOP: u8 = 0x00;
    
    /// Read DDB continue
    pub const READ_DDB_CONTINUE: u8 = 0xA8;
    
    /// Read DDB start
    pub const READ_DDB_START: u8 = 0xA1;
    
    /// Read memory continue
    pub const READ_MEMORY_CONTINUE: u8 = 0x3E;
    
    /// Read memory start
    pub const READ_MEMORY_START: u8 = 0x2E;
    
    /// Set address mode
    pub const SET_ADDRESS_MODE: u8 = 0x36;
    
    /// Set column address
    pub const SET_COLUMN_ADDRESS: u8 = 0x2A;
    
    /// Set display off
    pub const SET_DISPLAY_OFF: u8 = 0x28;
    
    /// Set display on
    pub const SET_DISPLAY_ON: u8 = 0x29;
    
    /// Set gamma curve
    pub const SET_GAMMA_CURVE: u8 = 0x26;
    
    /// Set page address
    pub const SET_PAGE_ADDRESS: u8 = 0x2B;
    
    /// Set partial columns
    pub const SET_PARTIAL_COLUMNS: u8 = 0x31;
    
    /// Set partial rows
    pub const SET_PARTIAL_ROWS: u8 = 0x30;
    
    /// Set pixel format
    pub const SET_PIXEL_FORMAT: u8 = 0x3A;
    
    /// Set scroll area
    pub const SET_SCROLL_AREA: u8 = 0x33;
    
    /// Set scroll start
    pub const SET_SCROLL_START: u8 = 0x37;
    
    /// Set tear off
    pub const SET_TEAR_OFF: u8 = 0x34;
    
    /// Set tear on
    pub const SET_TEAR_ON: u8 = 0x35;
    
    /// Set tear scanline
    pub const SET_TEAR_SCANLINE: u8 = 0x44;
    
    /// Soft reset
    pub const SOFT_RESET: u8 = 0x01;
    
    /// Write LUT
    pub const WRITE_LUT: u8 = 0x2D;
    
    /// Write memory continue
    pub const WRITE_MEMORY_CONTINUE: u8 = 0x3C;
    
    /// Write memory start
    pub const WRITE_MEMORY_START: u8 = 0x2C;
}

/// Pixel Format Values
#[allow(dead_code)]
pub mod pixel_format {
    /// 3 bits per pixel
    pub const PIXEL_FORMAT_3BPP: u8 = 0x01;
    
    /// 8 bits per pixel
    pub const PIXEL_FORMAT_8BPP: u8 = 0x02;
    
    /// 12 bits per pixel
    pub const PIXEL_FORMAT_12BPP: u8 = 0x03;
    
    /// 16 bits per pixel
    pub const PIXEL_FORMAT_16BPP: u8 = 0x05;
    
    /// 18 bits per pixel
    pub const PIXEL_FORMAT_18BPP: u8 = 0x06;
    
    /// 24 bits per pixel
    pub const PIXEL_FORMAT_24BPP: u8 = 0x07;
}

/// Address Mode Flags
#[allow(dead_code)]
pub mod address_mode {
    /// Page address order (vertical refresh)
    pub const PAGE_ADDRESS_ORDER: u8 = 1 << 7;
    
    /// Column address order (horizontal refresh)
    pub const COLUMN_ADDRESS_ORDER: u8 = 1 << 6;
    
    /// Page/column order
    pub const PAGE_COLUMN_ORDER: u8 = 1 << 5;
    
    /// Line address order
    pub const LINE_ADDRESS_ORDER: u8 = 1 << 4;
    
    /// RGB/BGR order
    pub const RGB_BGR_ORDER: u8 = 1 << 3;
    
    /// Display data latch order
    pub const DISPLAY_DATA_LATCH_ORDER: u8 = 1 << 2;
}

/// Helper Functions for DCS Commands

use crate::rk3588_mipi_dsi::{Rk3588MipiDsi, DsiError};

/// Send a DCS command with no parameters
pub fn dcs_write_0(dsi: &mut Rk3588MipiDsi, cmd: u8) -> Result<(), DsiError> {
    dsi.send_short_packet(MIPI_DSI_DCS_SHORT_WRITE, cmd, 0)
}

/// Send a DCS command with one parameter
pub fn dcs_write_1(dsi: &mut Rk3588MipiDsi, cmd: u8, param: u8) -> Result<(), DsiError> {
    dsi.send_short_packet(MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd, param)
}

/// Send a DCS command with multiple parameters
pub fn dcs_write_n(dsi: &mut Rk3588MipiDsi, cmd: u8, params: &[u8]) -> Result<(), DsiError> {
    if params.is_empty() {
        return dcs_write_0(dsi, cmd);
    }
    
    if params.len() == 1 {
        return dcs_write_1(dsi, cmd, params[0]);
    }
    
    // For long write, prepend command to data
    let mut data = [0u8; 256];
    if params.len() + 1 > 256 {
        return Err(DsiError::InvalidParameter);
    }
    
    data[0] = cmd;
    data[1..1 + params.len()].copy_from_slice(params);
    
    dsi.send_long_packet(MIPI_DSI_DCS_LONG_WRITE, &data[..1 + params.len()])
}

/// Helper function: Sleep Out
pub fn sleep_out(dsi: &mut Rk3588MipiDsi) -> Result<(), DsiError> {
    dcs_write_0(dsi, dcs_cmd::EXIT_SLEEP_MODE)
}

/// Helper function: Sleep In
pub fn sleep_in(dsi: &mut Rk3588MipiDsi) -> Result<(), DsiError> {
    dcs_write_0(dsi, dcs_cmd::ENTER_SLEEP_MODE)
}

/// Helper function: Display On
pub fn display_on(dsi: &mut Rk3588MipiDsi) -> Result<(), DsiError> {
    dcs_write_0(dsi, dcs_cmd::SET_DISPLAY_ON)
}

/// Helper function: Display Off
pub fn display_off(dsi: &mut Rk3588MipiDsi) -> Result<(), DsiError> {
    dcs_write_0(dsi, dcs_cmd::SET_DISPLAY_OFF)
}

/// Helper function: Set Pixel Format
pub fn set_pixel_format(dsi: &mut Rk3588MipiDsi, format: u8) -> Result<(), DsiError> {
    dcs_write_1(dsi, dcs_cmd::SET_PIXEL_FORMAT, format)
}

/// Helper function: Set Address Mode
pub fn set_address_mode(dsi: &mut Rk3588MipiDsi, mode: u8) -> Result<(), DsiError> {
    dcs_write_1(dsi, dcs_cmd::SET_ADDRESS_MODE, mode)
}

/// Helper function: Set Column Address
pub fn set_column_address(dsi: &mut Rk3588MipiDsi, start: u16, end: u16) -> Result<(), DsiError> {
    let params = [
        (start >> 8) as u8,
        (start & 0xFF) as u8,
        (end >> 8) as u8,
        (end & 0xFF) as u8,
    ];
    dcs_write_n(dsi, dcs_cmd::SET_COLUMN_ADDRESS, &params)
}

/// Helper function: Set Page Address
pub fn set_page_address(dsi: &mut Rk3588MipiDsi, start: u16, end: u16) -> Result<(), DsiError> {
    let params = [
        (start >> 8) as u8,
        (start & 0xFF) as u8,
        (end >> 8) as u8,
        (end & 0xFF) as u8,
    ];
    dcs_write_n(dsi, dcs_cmd::SET_PAGE_ADDRESS, &params)
}

/// Helper function: Soft Reset
pub fn soft_reset(dsi: &mut Rk3588MipiDsi) -> Result<(), DsiError> {
    dcs_write_0(dsi, dcs_cmd::SOFT_RESET)
}

